%{
/*
 * toolscan.l: the flex description file for the edbtool2 scanner.
 * Clunix, cezanne@clunix.com, 2005.2
 *
 * Copyright (c) 2005 by Clunix Inc. All Rights Reserved.
 */

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define MAX_STR_CONST	1024
#define MAX_BUF		1024

#include "edbtool2.h"
#include "toolparser.h"

void et2error(char *);

void (*edbtool2_input)(char *buf, int *result, int max);

/* Support for the readline and history libraries.  This allows
 * nicer input on the interactive part of input.
 */

/* Have input call the following function. */
#undef  YY_INPUT
#define YY_INPUT(buf,result,max_size) \
		edbtool2_input((char *)buf, &result, max_size)
#define YY_NO_INPUT

%}

%option nounput
%option yylineno
%option noyyalloc noyyrealloc noyyfree

%x sc_arg
%x sc_str
%x opt
%x typename
%x edexpr
%x sc_error

%x sc_mtrace
%x sc_treelock

%%
	char	buf[MAX_BUF];
	char	*buf_ptr = buf;

<<EOF>>		return ENDOFBUF;

#[^\n]*\n	

quit		BEGIN(sc_arg); return Quit;
help		BEGIN(sc_arg); return Help;
(ls|dir)	BEGIN(sc_arg); return Ls;
cd		BEGIN(sc_arg); return Cd;
create		BEGIN(sc_arg); return Create;
xecreate	BEGIN(sc_arg); return XeCreate;
create_cpy	BEGIN(sc_arg); return CreateCpy;
get		BEGIN(sc_arg); return Get;
set		BEGIN(sc_arg); return Set;
set_cpy		BEGIN(sc_arg); return SetCpy;
asrget		BEGIN(sc_arg); return ASRGet;
asrset		BEGIN(sc_arg); return ASRSet;
modules		BEGIN(sc_arg); return Modules;
rename		BEGIN(sc_arg); return Rename;
del		BEGIN(sc_arg); return Del;
xedelete	BEGIN(sc_arg); return XeDelete;
exec		BEGIN(sc_arg); return Exec;
snapshot	BEGIN(sc_arg); return Snapshot;
elect		BEGIN(sc_arg); return Elect;
shutdown	BEGIN(sc_arg); return Shutdown;
get_inherited_types	BEGIN(sc_arg); return GetInheritedTypes;
echo		BEGIN(sc_arg); return Echo;
prompt		BEGIN(sc_arg); return Prompt;

#DEBUG START
dbgset		BEGIN(sc_arg); return DbgSet;
mtrace		BEGIN(sc_mtrace); return MTrace;
treelock	BEGIN(sc_treelock); return TreeLock;
#DEBUG END

[\n[:blank:]]
[^\n[:blank:]]+	{
			et2lval.s_value = ecm_strdup(yytext);
			BEGIN(sc_error);
			return ErrorCmd;
		}

<sc_error>[^\n]+
<sc_error>\n	BEGIN(INITIAL);

<sc_arg>[[:blank:]]
<sc_arg>\\\n			
<sc_arg>^#[^\n]*\n

<sc_arg>%[1-9]		et2lval.s_value = get_arg(atoi(yytext + 1)); return Argument;

<sc_arg>[^\n\\[:blank:]\[\]\=\"<>\-]+	{
			et2lval.s_value = ecm_strdup(yytext);
			return Literal;
		}

<sc_arg>=		return Equal;
<sc_arg>\"		buf_ptr = buf; BEGIN(sc_str);
<sc_arg>\[		BEGIN(edexpr); return LeftSquare;
<sc_arg>\<		BEGIN(typename); return LeftAngle;
<sc_arg>\-		BEGIN(opt);
<sc_arg>\n		BEGIN(INITIAL); return ENDOFCMD;

<sc_arg>.		return Error;

<sc_str>[\n[:blank:]]+	ecm_strcpy(buf_ptr, yytext); buf_ptr += yyleng;
<sc_str>\"		{
				BEGIN(sc_arg);
				*buf_ptr = '\0';
				et2lval.s_value = ecm_strdup(buf);
				return String;
			}

<sc_str>\\[0-7]{1,3} {
			/* octal escape sequence */
			int	result;
			ecm_sscanf(yytext + 1, "%o", &result);
			if (result > 0xff)
				;
			*buf_ptr++ = result;
		}

<sc_str>\\[0-9]+	{
			/* generate error */
		}

<sc_str>\\n	*buf_ptr++ = '\n';
<sc_str>\\t	*buf_ptr++ = '\t';
<sc_str>\\r	*buf_ptr++ = '\r';
<sc_str>\\b	*buf_ptr++ = '\b';
<sc_str>\\f	*buf_ptr++ = '\f';
<sc_str>\\\\	*buf_ptr++ = '\\';
<sc_str>\\\"	*buf_ptr++ = '"';
<sc_str>\\[ ]	*buf_ptr++ = ' ';
<sc_str>\\(.|\n)	

<sc_str>[^\\\n[:blank:]\"]+	{
			char	*yptr = yytext;
			while (*yptr)
				*buf_ptr++ = *yptr++;
		}

<opt>force[[:blank:]]+	{
			BEGIN(sc_arg);
			return XeDeleteOpt;
		}

<opt>owner[[:blank:]]+	{
			BEGIN(sc_arg);
			et2lval.i_value = EDB_FIELD_OWNER;
			return Field;
		}
<opt>user[[:blank:]]+	{
			BEGIN(sc_arg);
			et2lval.i_value = EDB_FIELD_USER;
			return Field;
		}
<opt>group[[:blank:]]+	{
			BEGIN(sc_arg);
			et2lval.i_value = EDB_FIELD_GROUP;
			return Field;
		}
<opt>perm[[:blank:]]+	{
			BEGIN(sc_arg);
			et2lval.i_value = EDB_FIELD_PERM;
			return Field;
		}
<opt>update[[:blank:]]+	{
			BEGIN(sc_arg);
			et2lval.i_value = EDB_FIELD_ATTR_UPDATE;
			return Field;
		}
<opt>fetch[[:blank:]]+	{
			BEGIN(sc_arg);
			et2lval.i_value = EDB_FIELD_ATTR_FETCH;
			return Field;
		}
<opt>system[[:blank:]]+	{
			BEGIN(sc_arg);
			et2lval.i_value = EDB_FIELD_ATTR_SYSTEM;
			return Field;
		}
<opt>access[[:blank:]]+	{
			BEGIN(sc_arg);
			return Field;
		}
<opt>reactor[[:blank:]]+ {
			BEGIN(sc_arg);
			et2lval.i_value = EDB_FIELD_REACTOR;
			return Field;
		}

<opt>1		BEGIN(sc_arg); return ApplyOpt_1;
<opt>c		BEGIN(sc_arg); return ApplyOpt_c;
<opt>r		BEGIN(sc_arg); return ApplyOpt_r;
<opt>n		BEGIN(sc_arg); return ApplyOpt_n;
<opt>l		BEGIN(sc_arg); return ApplyOpt_l;
<opt>d		BEGIN(sc_arg); return ApplyOpt_d;
<opt>.		return ErrorOption;

<typename>[\n[:blank:]]+
<typename>[_[:alnum:]]+	{
			et2lval.s_value = ecm_strdup(yytext);
			return TypeName;
		}
<typename>\>	BEGIN(sc_arg); return RightAngle;
<typename>&	return Ampersand;
<typename>\*	return Esterik;
<typename>.	BEGIN(sc_error); return ErrorTypeName;

<edexpr>[^\]]+	et2lval.s_value = ecm_strdup(yytext); return EDExpression;
<edexpr>\]	BEGIN(sc_arg); return RightSquare;

<sc_mtrace>on		return MTraceOn;
<sc_mtrace>off		return MTraceOff;
<sc_mtrace>clear		return MTraceClear;
<sc_mtrace>report	return MTraceReport;
<sc_mtrace>[[:digit:]]+	et2lval.i_value = atoi(yytext); return MTraceLevel;
<sc_mtrace>[[:blank:]]+

<sc_mtrace>\n	BEGIN(INITIAL); return ENDOFCMD;
<sc_mtrace>.	BEGIN(sc_error); return MTraceError;

<sc_treelock>[[:blank:]]+

<sc_treelock>\n	BEGIN(INITIAL); return ENDOFCMD;
<sc_treelock>.	BEGIN(sc_error); return TreeLockError;

%%

void
et2error(char *msg)
{
}

void *
yyalloc(yy_size_t bytes)
{
	return ecm_malloc(bytes);
}

void *
yyrealloc(void *ptr, yy_size_t bytes)
{
	return ecm_realloc(ptr, bytes);
}

void
yyfree(void *ptr)
{
	ecm_free(ptr);
}
